package com.heisenhub.logs.common.utils;

import com.heisenhub.common.oauth.entity.UuaUser;
import com.heisenhub.common.redis.annotation.EnableXMRedisHandler;
import com.heisenhub.common.redis.annotation.RedisUtilsBean;
import com.heisenhub.common.redis.utils.RedisUtils;
import com.heisenhub.logs.common.annotation.LogsFieldDict;
import com.heisenhub.logs.common.dto.LogsRecordsDto;
import com.heisenhub.logs.common.enums.LogsOperateEnums;
import com.heisenhub.logs.common.qo.GMQo;
import com.heisnenhub.common.module.constant.HttpConstant;
import com.heisnenhub.common.module.enmus.BusinessTypeEnums;
import com.heisnenhub.common.module.exception.RRException;
import com.heisnenhub.common.module.utils.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;


@Slf4j
@RedisUtilsBean
public class LogsUtils {
    private static RedisUtils redisUtils =SpringUtils.getBean(RedisUtils.class);


    /**
     * 判断对象相同属性名  那些值 发生了改变
     *
     * @param originalObj 原对象
     * @param changeObj   改变得对象
     * @return 返回 发生改变的属性名
     */
    @SneakyThrows
    public static String fieldChange(Object originalObj, Object changeObj) {
        List<String> detailList = new ArrayList<>();
        Class<?> tClass = originalObj.getClass();
        Class<?> bClass = changeObj.getClass();

        for (Field tField : tClass.getDeclaredFields()) {
            for (Field bField : bClass.getDeclaredFields()) {
                if (tField.getName().equals(bField.getName())) {

                    String fieldName = bField.getName();

                    tField.setAccessible(true); // 设置 可读 属性
                    bField.setAccessible(true); // 设置 可读 属性
                    Object to = tField.get(originalObj);
                    Object bo = bField.get(changeObj);
                    if (HubObjectUtils.isEmpty(to)) to = "null";
                    if (HubObjectUtils.isEmpty(bo)) bo = "null";
                    if (!to.equals(bo)) {
                        StringBuilder details = new StringBuilder();
                        if (bField.isAnnotationPresent(LogsFieldDict.class)) {
                            LogsFieldDict fieldDict = bField.getAnnotation(LogsFieldDict.class);
                            fieldName = fieldDict.fName();

                            if (HubObjectUtils.isNotEmpty(fieldDict.propType())) {
                                for (String s : fieldDict.propType()) {
                                    String[] split = s.split("_");
                                    if (HubObjectUtils.isEmpty(split[1]))
                                        throw new RRException("@FieldDict propType字段 格式不正确");
                                    if (String.valueOf(to).equals(String.valueOf(split[0]))) {
                                        to = split[1];
                                    }
                                    if (String.valueOf(bo).equals(String.valueOf(split[0]))) {
                                        bo = split[1];
                                    }
                                }
                            }

//                            if (HubObjectUtils.isNotEmpty(fieldDict.dictType())) {
//                                SysDict toDictByCode = DictUtils.getSysDictByCode(to, fieldDict.dictType());
//                                SysDict boDictByCode = DictUtils.getSysDictByCode(bo, fieldDict.dictType());
//                                if (HubObjectUtils.isNotEmpty(toDictByCode)) to = toDictByCode.getValue();
//                                if (HubObjectUtils.isNotEmpty(boDictByCode)) bo = boDictByCode.getValue();
//                            }


                            if (HubObjectUtils.isNotEmpty(fieldDict.redisKey())) {
                                String redisKey = fieldDict.redisKey();
                                if(SpELUtils.isSpELExpression(redisKey)){
                                    ExpressionParser parser = new SpelExpressionParser();
                                    StandardEvaluationContext context = new StandardEvaluationContext();
                                    // 解析SpEL表达式
                                    redisKey = parser.parseExpression(redisKey).getValue(context, String.class);
                                }

                                Map<Object, Object> hmget = redisUtils.hmget(redisKey);
                                if (HubObjectUtils.isNotEmpty(hmget)) {
                                    if (to instanceof List || bo instanceof List) {
                                        List toList = new ArrayList();
                                        List boList = new ArrayList();
                                        if (HubObjectUtils.isNotEquals(to, "null"))
                                            toList = (List) to;
                                        if (HubObjectUtils.isNotEquals(bo, "null"))
                                            boList = (List) bo;

                                        /**
                                         * toList  和 boList 差集
                                         */
                                        List tsublist = listSub(toList, boList);

                                        if (HubObjectUtils.isNotEmpty(tsublist)) {
                                            details.append(fieldName);
                                            details.append(" 移除: ");
                                            for (Object too : tsublist) {
                                                if (HubObjectUtils.isNotEmpty(hmget.get(String.valueOf(too)))) {
                                                    Object o = hmget.get(String.valueOf(too));
                                                    if (HubObjectUtils.isNotEmpty(o)) details.append(o).append(" , ");
                                                }
                                            }
                                        }
                                        if (HubObjectUtils.isNotEmpty(details)) {
                                            detailList.add(details.toString());
                                            details = new StringBuilder();
                                        }
                                        List bsubolist = listSub(boList, toList);

                                        if (HubObjectUtils.isNotEmpty(bsubolist)) {
                                            details.append(fieldName).append(" 添加: ");
                                            for (Object boo : bsubolist) {
                                                if (HubObjectUtils.isNotEmpty(hmget.get(String.valueOf(boo)))) {
                                                    Object o = hmget.get(String.valueOf(boo));
                                                    if (HubObjectUtils.isNotEmpty(o)) details.append(o).append(" , ");
                                                }
                                            }
                                        }
                                        if (HubObjectUtils.isNotEmpty(details)) detailList.add(details.toString());
                                        continue;
                                    } else {
                                        if (HubObjectUtils.isNotEmpty(hmget.get(String.valueOf(to))))
                                            to = hmget.get(String.valueOf(to));
                                        if (HubObjectUtils.isNotEmpty(hmget.get(String.valueOf(bo))))
                                            bo = hmget.get(String.valueOf(bo));
                                    }

                                }
                            }

                            details.append(fieldName)
                                    .append(" 由 ")
                                    .append(to)
                                    .append(" 改变为：")
                                    .append(bo);
                            detailList.add(details.toString());
                        }
                    }
                }
            }
        }
        return CollectionUtils.isEmpty(detailList) ? null : GsonUtils.toJson(detailList);
    }


    @SneakyThrows
    public static String fieldAdd(Object changeObj) {
        List<String> detailList = new ArrayList<>();
        Class<?> bClass = changeObj.getClass();

        for (Field bField : bClass.getDeclaredFields()) {
            if (bField.isAnnotationPresent(LogsFieldDict.class)) {
                String fieldName = bField.getName();
                bField.setAccessible(true); // 设置 可读 属性
                Object bo = bField.get(changeObj);

                if (HubObjectUtils.isEmpty(bo)) continue;
                StringBuilder details = new StringBuilder();
                LogsFieldDict fieldDict = bField.getAnnotation(LogsFieldDict.class);
                fieldName = fieldDict.fName();

                if (HubObjectUtils.isNotEmpty(fieldDict.propType())) {
                    for (String s : fieldDict.propType()) {
                        String[] split = s.split("_");
                        if (HubObjectUtils.isEmpty(split[1]))
                            throw new RRException("@FieldDict propType字段 格式不正确");
                        if (String.valueOf(bo).equals(String.valueOf(split[0]))) {
                            bo = split[1];
                        }
                    }
                }


                if (HubObjectUtils.isNotEmpty(fieldDict.redisKey())) {
                    String redisKey = fieldDict.redisKey();
                    if(SpELUtils.isSpELExpression(redisKey)){
                        ExpressionParser parser = new SpelExpressionParser();
                        StandardEvaluationContext context = new StandardEvaluationContext();
                        // 解析SpEL表达式
                        redisKey = parser.parseExpression(redisKey).getValue(context, String.class);
                    }
                    Map<Object, Object> hmget = redisUtils.hmget(redisKey);
                    if (HubObjectUtils.isNotEmpty(hmget)) {
                        if (HubObjectUtils.isNotEmpty(hmget.get(String.valueOf(bo))))
                            bo = hmget.get(String.valueOf(bo));

                    }
                }

                details.append(fieldName)
                        .append(" 为：")
                        .append(bo);
                detailList.add(details.toString());
            }


        }
        return CollectionUtils.isEmpty(detailList) ? null : GsonUtils.toJson(detailList);
    }

    /**
     * 两个数组 的差集
     *
     * @param listv1
     * @param listv2
     * @return
     */
    private static List listSub(List listv1, List listv2) {
        List v1Copy = new ArrayList<>();
        v1Copy.addAll(listv1);

        List v2Copy = new ArrayList<>();
        v2Copy.addAll(listv2);

        v1Copy.removeAll(v2Copy);
        return v1Copy;
    }

}
